1 00:00:00,500 --> 00:00:01,250 Hey there. 2 00:00:01,250 --> 00:00:02,240 Welcome back. 3 00:00:02,240 --> 00:00:07,130 In this lecture, I would like to show you a neat module script that was created by another developer 4 00:00:07,130 --> 00:00:14,750 that allows us to easily manage and clean up instances and connections in our objects created by classes. 5 00:00:14,750 --> 00:00:20,750 When we create an object from a class, sometimes we will no longer need that object when, for example, 6 00:00:20,750 --> 00:00:24,500 the main part that object is associated with is destroyed. 7 00:00:24,500 --> 00:00:30,590 You can think of a class for tools where once the tool instance itself is destroyed, we would also 8 00:00:30,590 --> 00:00:34,190 like to destroy the object associated with that instance. 9 00:00:34,190 --> 00:00:39,920 This is where we would typically have a destroy function in our class to handle that cleanup. 10 00:00:39,920 --> 00:00:44,840 However, it can be a little annoying when we are listening to a bunch of different events and have 11 00:00:44,840 --> 00:00:50,390 several other instances, and then we have to manually disconnect those events and have to destroy those 12 00:00:50,390 --> 00:00:52,910 other instances inside of our destroy function. 13 00:00:52,910 --> 00:00:58,340 There may be times when we sometimes forget to disconnect an event, or we forget to destroy an instance, 14 00:00:58,340 --> 00:01:01,910 and that can potentially lead to some memory leak problems. 15 00:01:01,910 --> 00:01:06,830 For most instances in our game, when we have functions connected to their events and when those objects 16 00:01:06,830 --> 00:01:09,500 are destroyed, those connections are automatically cleaned up. 17 00:01:09,500 --> 00:01:11,780 But this is not the case for all events. 18 00:01:11,780 --> 00:01:17,090 For example, any connections to events and services have to be manually disconnected, such as the 19 00:01:17,090 --> 00:01:19,790 user input service and the run service, and so on. 20 00:01:20,180 --> 00:01:25,370 Any objects we create and parent somewhere in our game also have to be manually destroyed. 21 00:01:25,370 --> 00:01:30,650 So the main purpose of this module, which is called trove, is to help us track any sort of object 22 00:01:30,650 --> 00:01:34,850 during the runtime of our scripts that has to be cleaned up at some point in time. 23 00:01:34,850 --> 00:01:39,470 This helps us to avoid the worry of causing a memory leak in our code, because it's all handled by 24 00:01:39,470 --> 00:01:40,760 this module script. 25 00:01:40,760 --> 00:01:44,450 This module script can be a lifesaver down the road to prevent the problem. 26 00:01:44,450 --> 00:01:48,950 Where you encounter a memory leak that is ruining your game, and you're having trouble finding the 27 00:01:48,950 --> 00:01:50,540 source of that memory leak. 28 00:01:50,630 --> 00:01:55,190 The link to the module, along with the documentation has been attached to this lecture, so you can 29 00:01:55,190 --> 00:01:56,180 go ahead and grab it. 30 00:01:56,180 --> 00:01:59,270 And you can also follow along to see how this module works. 31 00:01:59,540 --> 00:02:04,010 First, let's go ahead and take a look at this example tool class I've created. 32 00:02:05,500 --> 00:02:10,330 Inside of this simple class, we have our table that is representing the class, and then we have the 33 00:02:10,330 --> 00:02:12,640 meta table to attach to all our objects. 34 00:02:12,640 --> 00:02:16,240 We have our constructor here, and the constructor takes a tool. 35 00:02:16,240 --> 00:02:19,510 It associates that tool with our object itself. 36 00:02:19,510 --> 00:02:23,860 It creates some events, some other instances, sets them somewhere in the workspace. 37 00:02:23,860 --> 00:02:26,200 And we also listen to some other events here. 38 00:02:26,680 --> 00:02:31,810 And then eventually when the tool itself or the instance is destroyed, then we obviously want to go 39 00:02:31,810 --> 00:02:35,200 ahead and destroy the object associated with it as well. 40 00:02:35,200 --> 00:02:41,110 So inside of this destroy function, as you can see, we're removing the object from our cache up here 41 00:02:41,110 --> 00:02:44,080 where we store all of our objects. 42 00:02:44,080 --> 00:02:47,740 And afterwards here we have to manually disconnect these events. 43 00:02:47,740 --> 00:02:50,530 We have to destroy these other instances. 44 00:02:50,530 --> 00:02:52,000 This is a lot of work. 45 00:02:52,000 --> 00:02:57,430 And sometimes you may wish that there is an easier way to do this, because later on, if we decided 46 00:02:57,430 --> 00:03:03,190 to add more instances or listen to some other connections, we may forget to disconnect those or destroy 47 00:03:03,190 --> 00:03:03,370 them. 48 00:03:03,370 --> 00:03:05,110 Down here in our destroy function. 49 00:03:05,110 --> 00:03:07,780 And that can lead to issues like memory leaks. 50 00:03:07,780 --> 00:03:09,970 So this is where trove comes in. 51 00:03:09,970 --> 00:03:15,280 So I'm going to go ahead and require trove by first referring to the location that it's stored in. 52 00:03:15,280 --> 00:03:17,350 I have it placed inside of replicated storage. 53 00:03:17,350 --> 00:03:21,760 So I'll just call or create a variable for replicated storage. 54 00:03:22,320 --> 00:03:27,630 And then I can go ahead and refer to my trove and we'll require from replicated storage trove. 55 00:03:27,900 --> 00:03:33,180 And then we can go ahead and use this trove to create a new object or a new trove object. 56 00:03:33,180 --> 00:03:37,620 And inside of that trove object is where we can store connections, we can store instances. 57 00:03:37,620 --> 00:03:42,510 And whenever we decide to clean up, we can call the cleanup function on that trove. 58 00:03:42,510 --> 00:03:48,120 And it goes ahead and deletes and disconnects all of those events and instances for us without us having 59 00:03:48,120 --> 00:03:50,820 to manually do it within our destroy function. 60 00:03:51,430 --> 00:03:56,890 So inside of my tool class, what I could do is I could create a new key for my trove. 61 00:03:56,890 --> 00:04:01,720 I'm just going to name it underscore, underscore, trove to signify that this is private. 62 00:04:01,720 --> 00:04:07,720 And I don't want any other scripts to really be messing with this key inside of my object. 63 00:04:07,720 --> 00:04:11,740 So I'm just putting the two underlines to denote it as a private key. 64 00:04:12,390 --> 00:04:15,090 And then I can set that equal to true revenue. 65 00:04:15,360 --> 00:04:20,430 And now we have our object here where we could go ahead and add these instances inside of the object. 66 00:04:20,430 --> 00:04:23,670 And we can also add these connections into our object. 67 00:04:23,670 --> 00:04:29,340 And then when our part gets destroyed, we can easily just clean up all of those things by calling a 68 00:04:29,340 --> 00:04:31,800 function on our trove object. 69 00:04:32,410 --> 00:04:37,990 Now, before I completely start setting up this trove, I first want to demonstrate how this class actually 70 00:04:37,990 --> 00:04:40,060 works in its default state. 71 00:04:40,090 --> 00:04:43,960 So inside of this script, I've simply required my tool class. 72 00:04:43,960 --> 00:04:49,030 I've created an example tool object here where I'm just passing a new tool instance. 73 00:04:49,030 --> 00:04:50,440 And here's my new tool. 74 00:04:50,440 --> 00:04:54,280 And then I'm going to wait 10s and then afterwards destroy my tool object. 75 00:04:54,280 --> 00:05:00,880 So within those 10s we should have like for example, this heartbeat function running multiple times 76 00:05:00,880 --> 00:05:02,680 per second and stuff like that. 77 00:05:02,680 --> 00:05:04,630 So if we go and play test the game. 78 00:05:05,600 --> 00:05:09,800 As you can see, our object there is executing with that heartbeat. 79 00:05:09,800 --> 00:05:14,540 And if we look inside of our spawn location, here are those other instances associated with our object 80 00:05:14,540 --> 00:05:15,530 that I created. 81 00:05:15,770 --> 00:05:19,430 And then eventually, after those 10s are up, we destroy those objects. 82 00:05:19,430 --> 00:05:24,650 We disconnect that function from that event, and it's no longer executing and our object has been destroyed. 83 00:05:25,590 --> 00:05:30,720 But like I said earlier, that can be a little tedious since we have to manually do all of the work 84 00:05:30,720 --> 00:05:32,760 right here inside of our destroy function. 85 00:05:33,060 --> 00:05:35,670 So this is where our trove comes into play. 86 00:05:35,700 --> 00:05:41,070 For example, here, when we create our new Bindable event, what we can do is we can store it inside 87 00:05:41,070 --> 00:05:42,210 of our trove. 88 00:05:42,240 --> 00:05:48,180 You can think of the trove as a collection of stuff inside of the script, or as a bin or a container. 89 00:05:48,180 --> 00:05:52,920 And once you're done using the stuff inside of the trove, we go ahead and dump it out and trash it. 90 00:05:53,280 --> 00:05:57,510 So to add a new object to my trove I'm going to do is first refer to it. 91 00:05:57,510 --> 00:06:00,780 And then we have a function which is called add. 92 00:06:00,780 --> 00:06:06,510 And this allows us to add an object to our trove such as this new Bindable event right here. 93 00:06:06,510 --> 00:06:10,860 So I can call the add function and just pass self dot some event. 94 00:06:11,490 --> 00:06:15,660 And now we have stored this Bindable event inside of the trove. 95 00:06:15,660 --> 00:06:21,510 And that means whenever we clean up the trove this is automatically going to be destroyed for us. 96 00:06:21,870 --> 00:06:24,120 We can also do all of this on the same line. 97 00:06:24,120 --> 00:06:28,800 So for example here I could do self dot underscore underscore trove add. 98 00:06:28,800 --> 00:06:32,610 And then inside of here I can call my instance dot new function. 99 00:06:32,610 --> 00:06:38,250 And then this will also return back the new texture that we created and store it inside of this variable. 100 00:06:38,250 --> 00:06:40,230 Both of these ways work. 101 00:06:40,230 --> 00:06:44,820 But sometimes you may want to do it this way because it's one line instead of two lines. 102 00:06:44,820 --> 00:06:47,670 But whatever way works for you doesn't really matter. 103 00:06:47,670 --> 00:06:54,540 So now these two instances are inside of our trove, and that means now we don't have to manually destroy 104 00:06:54,540 --> 00:06:56,610 those instances in our destroy function. 105 00:06:56,610 --> 00:06:59,520 Instead, what we could do is refer to the trove. 106 00:06:59,520 --> 00:07:03,600 So dot underscore underscore trove and then call the clean function. 107 00:07:03,600 --> 00:07:06,960 And that will automatically destroy those instances for us. 108 00:07:06,960 --> 00:07:10,230 So if we go take a look by running our game. 109 00:07:11,450 --> 00:07:16,070 And we look in the workspace here, you can see those objects inside of our spawn location. 110 00:07:16,070 --> 00:07:18,200 And then once those 10s are up. 111 00:07:18,970 --> 00:07:22,690 As you can see, they have been automatically destroyed by our trove. 112 00:07:23,340 --> 00:07:28,620 And of course, we can do the exact same thing with these connections as well with our events. 113 00:07:28,620 --> 00:07:35,940 So inside of our trove, we also have a function to connect to a signal, pass a function, and then 114 00:07:35,940 --> 00:07:40,590 when the trove is cleaned up it's going to automatically disconnect that function from that event. 115 00:07:40,590 --> 00:07:44,730 So for example here I want to connect to the run service heartbeat event. 116 00:07:45,000 --> 00:07:48,000 So we'll pass that and then pass our function. 117 00:07:48,000 --> 00:07:51,870 And I'll just basically copy what happens here and paste it in there. 118 00:07:51,870 --> 00:07:53,340 And then we can delete this. 119 00:07:53,490 --> 00:07:58,860 And now we don't have to store that connection inside of our object, which means we don't have to manually 120 00:07:58,860 --> 00:07:59,580 disconnect it. 121 00:07:59,580 --> 00:08:00,990 So we can go ahead and delete that. 122 00:08:01,380 --> 00:08:06,570 Because every time we call the clean function on our trove, that connection right here to our heartbeat 123 00:08:06,570 --> 00:08:08,670 event is automatically going to be cleaned up. 124 00:08:08,670 --> 00:08:11,820 And the same thing we could do for this right here as well. 125 00:08:11,820 --> 00:08:16,500 Now another valid way you can add this connection to our trove is by using the add function instead 126 00:08:16,500 --> 00:08:17,760 of the connect function. 127 00:08:17,760 --> 00:08:23,700 So for example I could do self dot underscore underscore trove and then add and inside of this function 128 00:08:23,700 --> 00:08:29,550 what I can do is just copy this and paste that in there and then delete that. 129 00:08:29,640 --> 00:08:32,550 And this is the exact same thing as doing this up here. 130 00:08:32,550 --> 00:08:40,320 Because remember when we connect to this event what returns is that connection that we can disconnect. 131 00:08:40,320 --> 00:08:43,170 And that connection gets passed to the add function. 132 00:08:43,170 --> 00:08:47,910 And then our trove is automatically going to clean up or disconnect that connection for us. 133 00:08:48,330 --> 00:08:53,250 So now we don't have to manually disconnect that other connection right here either. 134 00:08:53,790 --> 00:09:00,240 So we've just reduced four lines of code into a single line of code, where everything is stored inside 135 00:09:00,240 --> 00:09:03,810 of our trove, and all we need to do is call the clean function. 136 00:09:03,810 --> 00:09:08,820 And it's going to disconnect these events for us, and it's going to automatically delete these instances 137 00:09:08,820 --> 00:09:09,840 for us as well. 138 00:09:09,840 --> 00:09:11,790 So now if we go and play the game. 139 00:09:14,310 --> 00:09:16,020 As you can see, our object is running. 140 00:09:16,020 --> 00:09:20,970 We go look at our spawn location, there are our objects, and then eventually. 141 00:09:22,860 --> 00:09:23,490 There we go. 142 00:09:23,490 --> 00:09:24,870 Those objects get destroyed. 143 00:09:24,870 --> 00:09:29,640 And as you can see, the event also got disconnected thanks to our trove. 144 00:09:30,460 --> 00:09:36,880 So as you can see, trove is an incredibly simple module script, yet it is an extremely useful one 145 00:09:36,880 --> 00:09:41,080 and can save us from the headache of memory leaks down the road in our games. 146 00:09:41,080 --> 00:09:45,820 As I stated earlier, you can grab the trove module script attached to the lecture and take a look at 147 00:09:45,820 --> 00:09:47,620 the documentation for it as well. 148 00:09:47,620 --> 00:09:51,130 That's all for me for this lecture and I will see you in the next one.